package com.jinke.api.modules.app.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.common.util.Global;
import com.jinke.api.modules.app.enums.SysMessageReadStatus;
import com.jinke.api.modules.app.enums.SysMessageType;
import com.jinke.api.modules.app.mapper.SysMessageMapper;
import com.jinke.api.modules.app.model.SysMessage;
import com.jinke.api.modules.app.model.UserSysMessage;
import com.jinke.api.modules.app.request.AdminMessageQueryRequest;
import com.jinke.api.modules.app.request.MessageQueryRequest;
import com.jinke.api.modules.app.request.MessageReadRequest;
import com.jinke.api.modules.app.request.SysMessageCreateRequest;
import com.jinke.api.modules.app.response.SysMessageVO;
import com.jinke.api.modules.app.service.SysMessageService;
import com.jinke.api.modules.app.service.UserSysMessageService;
import com.jinke.api.modules.app.util.JavaMailUntil;
import com.jinke.api.modules.ums.model.UmsAdmin;
import com.jinke.api.modules.ums.service.UmsAdminService;
import com.jinke.api.modules.ums.util.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author macro
 * @since 2024-01-30
 */
@Service
@Slf4j
public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMessage> implements SysMessageService {

    @Autowired
    private UserSysMessageService userSysMessageService;
    @Autowired
    private UmsAdminService umsAdminService;

    @Override
    public Page<SysMessageVO> list(MessageQueryRequest request) {


        SysMessageReadStatus readStatus = request.getReadStatus();

        Integer userId = request.getUserId();

        String keyword = request.getKeyword();
        SysMessageType sysMessageType = request.getType();
        List<Integer> messageIds = new ArrayList<>();
        List<SysMessage> sysMessages = new ArrayList<>();
        if (StringUtils.isNotBlank(keyword) || sysMessageType != null) {
            LambdaQueryWrapper<SysMessage> sysWrapper = new LambdaQueryWrapper<>();
            sysWrapper.eq(sysMessageType != null, SysMessage::getType, sysMessageType)
                    .and(StringUtils.isNotBlank(keyword), w -> {
                        w.like(SysMessage::getTitle, keyword).
                                or().like(SysMessage::getContent, keyword);
                    }).orderByDesc(SysMessage::getId);
            sysMessages = list(sysWrapper);
            messageIds = sysMessages.stream().map(SysMessage::getId).filter(Objects::nonNull).collect(Collectors.toList());
            if (CollectionUtil.isEmpty(messageIds)) {
                messageIds = Arrays.asList(-1);
            }
        }

        LambdaQueryWrapper<UserSysMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(readStatus != null, UserSysMessage::getStatus, readStatus)
                .eq(userId != null, UserSysMessage::getUserId, userId)
                .in(CollectionUtil.isNotEmpty(messageIds), UserSysMessage::getSysMessageId, messageIds)
        ;

        Page<UserSysMessage> page = new Page<>(request.getPageNum(), request.getPageSize());
        Page<UserSysMessage> userSysMessages = userSysMessageService.page(page, wrapper);

        List<UserSysMessage> userSysMessagesRecords = userSysMessages.getRecords();
        Page<SysMessageVO> finalResults = new Page<>();
        if (CollectionUtil.isNotEmpty(userSysMessagesRecords)) {
            if (CollectionUtil.isEmpty(messageIds)) {
                Set<Integer> curMessageIds = userSysMessagesRecords.stream().map(UserSysMessage::getSysMessageId).collect(Collectors.toSet());
                LambdaQueryWrapper<SysMessage> sysWrapper = new LambdaQueryWrapper<>();
                sysWrapper.in(CollectionUtil.isNotEmpty(curMessageIds), SysMessage::getId, curMessageIds)
                        .orderByDesc(SysMessage::getId);
                sysMessages = list(sysWrapper);
            }

            if (CollectionUtil.isNotEmpty(sysMessages)) {
                Map<Integer, SysMessage> sysMessageMap = sysMessages.stream()
                        .collect(Collectors.toMap(SysMessage::getId, Function.identity()));

                List<SysMessageVO> vos = new ArrayList<>();
                userSysMessagesRecords.forEach(x -> {
                    SysMessageVO vo = new SysMessageVO();
                    BeanUtils.copyProperties(x, vo);
                    SysMessage sysMessage = sysMessageMap.get(x.getSysMessageId());
                    if (sysMessage != null) {
                        BeanUtils.copyProperties(sysMessage, vo);
                    }
                    vos.add(vo);
                });
                finalResults.setRecords(vos);
                finalResults.setSize(userSysMessages.getSize()).setTotal(userSysMessages.getTotal()).setCurrent(userSysMessages.getCurrent());
            }
        }


        return finalResults;
    }

    @Override
    public Page<SysMessage> listSysMessage(AdminMessageQueryRequest request) {
        String keyword = request.getKeyword();
        SysMessageType sysMessageType = request.getType();
        Page<SysMessage> page = new Page<>(request.getPageNum(), request.getPageSize());
        LambdaQueryWrapper<SysMessage> sysWrapper = new LambdaQueryWrapper<>();
        sysWrapper.eq(sysMessageType != null, SysMessage::getType, sysMessageType)
                .and(StringUtils.isNotBlank(keyword), w -> {
                    w.like(SysMessage::getTitle, keyword).
                            or().like(SysMessage::getContent, keyword);
                }).orderByDesc(SysMessage::getId);
        return page(page, sysWrapper);
    }

    @Override
    public Long unread() {

        return userSysMessageService.count(new LambdaQueryWrapper<UserSysMessage>()
                .eq(UserSysMessage::getUserId, UserUtil.getUserInfo().getId())
                .eq(UserSysMessage::getStatus, SysMessageReadStatus.UN_READ)
        );
    }

    @Override
    public CommonResult create(SysMessageCreateRequest request) {

        // 创建一条消息
        SysMessage sysMessage = new SysMessage();
        BeanUtils.copyProperties(request, sysMessage);
        save(sysMessage);

        // 发送给所有人
        Set<Integer> userIds = umsAdminService.list(new LambdaQueryWrapper<UmsAdmin>().select(UmsAdmin::getId)).stream().map(UmsAdmin::getId)
                .filter(Objects::nonNull).collect(Collectors.toSet());
        if (CollectionUtil.isNotEmpty(userIds)) {
            List<UserSysMessage> userSysMessages = userIds.stream().map(x -> {
                UserSysMessage userSysMessage = new UserSysMessage();
                userSysMessage.setUserId(x);
                userSysMessage.setSysMessageId(sysMessage.getId());
                userSysMessage.setStatus(SysMessageReadStatus.UN_READ);
                return userSysMessage;
            }).collect(Collectors.toList());
            userSysMessageService.saveBatch(userSysMessages);
        }
        return CommonResult.success();
    }


    public Integer createOneSysmsg(SysMessageCreateRequest request) {

        // 创建一条消息
        SysMessage sysMessage = new SysMessage();
        BeanUtils.copyProperties(request, sysMessage);
        save(sysMessage);
        return  sysMessage.getId();

    }
    @Override
    public CommonResult read(MessageReadRequest request) {
        List<Integer> ids = request.getIds();
        userSysMessageService.update(new LambdaUpdateWrapper<UserSysMessage>()
                .in(CollectionUtil.isNotEmpty(ids), UserSysMessage::getSysMessageId, ids)
                .set(UserSysMessage::getStatus, SysMessageReadStatus.READ))
        ;
        return CommonResult.success();
    }

    @Override
    public CommonResult delete(MessageReadRequest request) {
        List<Integer> ids = request.getIds();
        userSysMessageService.remove(new LambdaQueryWrapper<UserSysMessage>()
                .in(CollectionUtil.isNotEmpty(ids), UserSysMessage::getSysMessageId, ids));

        return CommonResult.success();
    }

    @Override
    public CommonResult deleteSysMessage(MessageReadRequest request) {
        List<Integer> ids = request.getIds();

        removeBatchByIds(ids);
        userSysMessageService.remove(new LambdaQueryWrapper<UserSysMessage>()
                .in(CollectionUtil.isNotEmpty(ids), UserSysMessage::getSysMessageId, ids));

        return CommonResult.success();
    }

    /**
     * 用户反馈发送邮件到邮箱
     * @return
     */
    @Override
    public CommonResult sendMailToUs(   String htmlContent,List<String> onlineFileUrl,String subject,String emailAdress) {
        try {
            Session session = JavaMailUntil.createSessionForQQ();
            //2.创建邮件对象
            MimeMessage message = new MimeMessage(session);
            //设置邮件主题
            message.setSubject(subject);
            //设置邮件内容
            //message.setText(JSON.toJSONString(contactUsReqParam));

            // 设置成富文本格式的内容
            // 创建 MimeMultipart 对象
            MimeMultipart multipart = new MimeMultipart();
            // 创建 MimeBodyPart 对象，用于存放富文本内容
            MimeBodyPart textPart = new MimeBodyPart();

            textPart.setContent(htmlContent, "text/html; charset=utf-8");
            // 将富文本内容添加到 MimeMultipart 中
            multipart.addBodyPart(textPart);


            if (CollectionUtils.isNotEmpty(onlineFileUrl)){
                for (String url : onlineFileUrl) {

                    // 本地文件
                    //   File attachmentFile = new File("C:\\Users\\Administrator\\Desktop\\无标题.sql");
                    // 下载在线文件并添加为附件
                    File downloadedFile = downloadFile(url);
                    MimeBodyPart attachmentPart = new MimeBodyPart();
                    FileDataSource fileDataSource = new FileDataSource(downloadedFile);
                    attachmentPart.setDataHandler(new DataHandler(fileDataSource));
                    attachmentPart.setFileName(MimeUtility.encodeText(downloadedFile.getName()));
                    multipart.addBodyPart(attachmentPart);
                }
            }

            message.setContent(multipart);

            //设置发件人
            message.setFrom(new InternetAddress("husuruo@qq.com"));
            InternetAddress address;
            //设置收件人
            if (emailAdress==null){
                  address = new InternetAddress("service@ship-cheap.com");
            }else {
                  address = new InternetAddress(emailAdress);

            }
            message.setRecipient(MimeMessage.RecipientType.TO, address);
            //设置秘送人
            InternetAddress[] ccAddresses = {

                    new InternetAddress("husuruo@ship-cheap.com")
            };
            InternetAddress[] txBccAddresses = {

                    new InternetAddress("husuruo@ship-cheap.com"),
                   new InternetAddress("yangxi@ship-cheap.com")
            };
            if (emailAdress.equalsIgnoreCase(Global.EMAIL_TACHENG)){

                message.setRecipients(MimeMessage.RecipientType.BCC, txBccAddresses);
            }else {

                message.setRecipients(MimeMessage.RecipientType.BCC, ccAddresses);
            }
            //3.发送邮件
            Transport.send(message);
            log.info("发邮件成功"+emailAdress);
        }    catch (Exception e) {
            log.info("发邮件报错"+emailAdress+" error:"+e.getMessage());
            return   CommonResult.failed();
        }
        return CommonResult.success();
    }

    /**
     * @Author: hhp
     * @Description: 发送系统消息给指定人
     * @Data: 2024/8/21 14:05
     * @return: com.jinke.api.common.api.CommonResult
     * @throws:
     **/
    @Override
    public CommonResult sendMessageToUsers(Integer userId  , Integer messageId) {

        // 发送指定人
        List<UserSysMessage> userSysMessages = Lists.newArrayList();
                    UserSysMessage userSysMessage = new UserSysMessage();
                    userSysMessage.setUserId(userId);
                    userSysMessage.setSysMessageId(messageId);
                    userSysMessage.setStatus(SysMessageReadStatus.UN_READ);
                    userSysMessages.add(userSysMessage);
            userSysMessageService.saveBatch(userSysMessages);
        return CommonResult.success();
    }


    public static File downloadFile(String fileUrl) throws IOException {
        URL url = new URL(fileUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        int responseCode = connection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String fileName = getFileNameFromUrl(fileUrl);
            File file = new File(fileName);
            try (InputStream inputStream = connection.getInputStream();
                 FileOutputStream outputStream = new FileOutputStream(file)) {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer))!= -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            }
            return file;
        } else {
            throw new IOException("Failed to download file. Response code: " + responseCode);
        }
    }

    public static String getFileNameFromUrl(String url) {
        int startIndex = url.lastIndexOf('/') + 1;
        int endIndex = url.indexOf('?', startIndex);
        if (endIndex == -1) {
            endIndex = url.length();
        }
        return url.substring(startIndex, endIndex);
    }




}
